﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Data.SqlClient;
using System.Data;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Data.SQLite;

using CRM.Dictionary.Service;
using CRM.Dictionary.Box;
using CRM.Entity;
using CRM.SQLiteHelper;
using CRM.Common;

namespace CRM.Dictionary.Start
{
   public class Program
    {
        static void Main()
        {
            var watch = Stopwatch.StartNew();

            //加载索引
            new LoadHelper().Start();

            watch.Stop();

            LogHelper.WriteLog(string.Format("所有表数据全部加载完毕，总耗时：{0}ms", watch.ElapsedMilliseconds));
        }
    }

    public class LockMe
    {
        //默认的容纳大小为“硬件线程“数
        public static CountdownEvent cde = new CountdownEvent(Environment.ProcessorCount);
    }

    public class LoadHelper
    {
        SQLiteDataReader sr;

        List<string> idList;

        int idCount;

        //一个线程读取1000条
        int smallID = 1000;

        int taskCount = 0;
        public void Start()
        {
            #region News_Detail
             sr = DbHelperSQL.ExecuteReader("select news_id from [News_Detail]");

            //数据库记录个数
            idList = new List<string>();

            while (sr.Read())
                idList.Add(sr[0].ToString());

            sr.Close();

            idCount = idList.Count;

            taskCount = idList.Count % smallID == 0 ? idList.Count / smallID : idList.Count / smallID + 1;

            LogHelper.WriteLog(string.Format("智能计算，News_Detail需要开启:{0}个task,每个task加载:{1}条", taskCount, smallID));

            //开启时间
            var watch = Stopwatch.StartNew();
            //重置信号
            LockMe.cde.Reset(taskCount);

            for (int i = 0; i < taskCount; i++)
            {
                Task.Factory.StartNew((obj) =>
                {
                    new LoadEntity().LoadNews_Detail(obj);

                }, idList.Skip(i * smallID).Take(smallID).ToList());
            }

            //等待所有任务执行完毕
            LockMe.cde.Wait();

            LogHelper.WriteLog(string.Format("\nNews_Detail表数据全部加载完毕！总共加载：{0},耗时:{1}\n", DictionaryBox.News_DetailDictionary.Keys.Count, watch.ElapsedMilliseconds));
            
         #endregion News_Detail
         
            #region News_Type
             sr = DbHelperSQL.ExecuteReader("select type_id from [News_Type]");

            //数据库记录个数
            idList = new List<string>();

            while (sr.Read())
                idList.Add(sr[0].ToString());

            sr.Close();

            idCount = idList.Count;

            taskCount = idList.Count % smallID == 0 ? idList.Count / smallID : idList.Count / smallID + 1;

            LogHelper.WriteLog(string.Format("智能计算，News_Type需要开启:{0}个task,每个task加载:{1}条", taskCount, smallID));

             watch = Stopwatch.StartNew();
            //重置信号
            LockMe.cde.Reset(taskCount);

            for (int i = 0; i < taskCount; i++)
            {
                Task.Factory.StartNew((obj) =>
                {
                    new LoadEntity().LoadNews_Type(obj);

                }, idList.Skip(i * smallID).Take(smallID).ToList());
            }

            //等待所有任务执行完毕
            LockMe.cde.Wait();

            LogHelper.WriteLog(string.Format("\nNews_Type表数据全部加载完毕！总共加载：{0},耗时:{1}\n", DictionaryBox.News_TypeDictionary.Keys.Count, watch.ElapsedMilliseconds));
            
         #endregion News_Type
         
            #region Sys_UserInfo
             sr = DbHelperSQL.ExecuteReader("select user_id from [Sys_UserInfo]");

            //数据库记录个数
            idList = new List<string>();

            while (sr.Read())
                idList.Add(sr[0].ToString());

            sr.Close();

            idCount = idList.Count;

            taskCount = idList.Count % smallID == 0 ? idList.Count / smallID : idList.Count / smallID + 1;

            LogHelper.WriteLog(string.Format("智能计算，Sys_UserInfo需要开启:{0}个task,每个task加载:{1}条", taskCount, smallID));

             watch = Stopwatch.StartNew();
            //重置信号
            LockMe.cde.Reset(taskCount);

            for (int i = 0; i < taskCount; i++)
            {
                Task.Factory.StartNew((obj) =>
                {
                    new LoadEntity().LoadSys_UserInfo(obj);

                }, idList.Skip(i * smallID).Take(smallID).ToList());
            }

            //等待所有任务执行完毕
            LockMe.cde.Wait();

            LogHelper.WriteLog(string.Format("\nSys_UserInfo表数据全部加载完毕！总共加载：{0},耗时:{1}\n", DictionaryBox.Sys_UserInfoDictionary.Keys.Count, watch.ElapsedMilliseconds));
            
         #endregion Sys_UserInfo
         
        }

        public class LoadEntity
        {
            #region News_Detail
            public void LoadNews_Detail(object obj)
            {
                try
                {
                    var listID = obj as List<string>;

                    string sqlWhere = string.Join("','", listID);

                    var dt = DbHelperSQL.Query("select * from News_Detail where news_id in ('" + sqlWhere + "')").Tables[0];

                    Parallel.ForEach(Partitioner.Create(0, dt.Rows.Count), (i) =>
                    {
                        for (int j = i.Item1; j < i.Item2; j++)
                        {
                            DictionaryBox.News_DetailDictionary.TryAdd(Convert.ToInt32(dt.Rows[j]["news_id"]),
                                                            new News_Detail(dt.Rows[j]));
                        }
                    });
                }
                catch (Exception e)
                {
                   LogHelper.WriteLog(e.Message);
                }
                finally
                {
                    LockMe.cde.Signal();
                }
            }
            #endregion News_Detail
            
            #region News_Type
            public void LoadNews_Type(object obj)
            {
                try
                {
                    var listID = obj as List<string>;

                    string sqlWhere = string.Join("','", listID);

                    var dt = DbHelperSQL.Query("select * from News_Type where type_id in ('" + sqlWhere + "')").Tables[0];

                    Parallel.ForEach(Partitioner.Create(0, dt.Rows.Count), (i) =>
                    {
                        for (int j = i.Item1; j < i.Item2; j++)
                        {
                            DictionaryBox.News_TypeDictionary.TryAdd(Convert.ToInt32(dt.Rows[j]["type_id"]),
                                                            new News_Type(dt.Rows[j]));
                        }
                    });
                }
                catch (Exception e)
                {
                   LogHelper.WriteLog(e.Message);
                }
                finally
                {
                    LockMe.cde.Signal();
                }
            }
            #endregion News_Type
            
            #region Sys_UserInfo
            public void LoadSys_UserInfo(object obj)
            {
                try
                {
                    var listID = obj as List<string>;

                    string sqlWhere = string.Join("','", listID);

                    var dt = DbHelperSQL.Query("select * from Sys_UserInfo where user_id in ('" + sqlWhere + "')").Tables[0];

                    Parallel.ForEach(Partitioner.Create(0, dt.Rows.Count), (i) =>
                    {
                        for (int j = i.Item1; j < i.Item2; j++)
                        {
                            DictionaryBox.Sys_UserInfoDictionary.TryAdd(Convert.ToInt32(dt.Rows[j]["user_id"]),
                                                            new Sys_UserInfo(dt.Rows[j]));
                        }
                    });
                }
                catch (Exception e)
                {
                   LogHelper.WriteLog(e.Message);
                }
                finally
                {
                    LockMe.cde.Signal();
                }
            }
            #endregion Sys_UserInfo
            

        }
    }
}
